import { Buffer } from 'buffer'
import { Header } from './ds'
import { tokenName, blackUserTag, timeStamp, role, userName } from '@/utils/constants'

export function checkToken (): string {
  const k1 = sessionStorage.getItem(tokenName)
  if (k1 !== null) {
    return k1
  }

  const k2 = localStorage.getItem(tokenName)
  const t2 = localStorage.getItem(timeStamp)

  const timeOut = 60 * 60 * 72
  if (k2 !== null && t2 !== null) {
    const cur = Math.floor(new Date().getTime() / 1000)
    const t = Math.floor(parseInt(t2) / 1000)
    if (t < cur && cur - t < timeOut) {
      return k2
    }
  }
  return ''
}

function priority (role: string): number {
  if (role === '') {
    return 0
  }

  if (role === 'editor') {
    return 10
  }

  if (role === 'admin') {
    return 100
  }

  return 0
}

export function getFromLocal (key: string): string {
  const value = localStorage.getItem(key)
  if (value === null) {
    return ''
  }
  const t2 = localStorage.getItem(timeStamp)
  if (t2 === null) {
    return ''
  }
  const t = Math.ceil(parseInt(t2) / 1000)
  const cur = Math.ceil(new Date().getTime() / 1000)
  if (cur > t && cur - t <= 3600 * 24) {
    return value
  }
  return ''
}

export function checkRole (required: string): boolean {
  let curRole = sessionStorage.getItem(role)
  if (curRole === null) {
    curRole = getFromLocal(role)
    if (curRole === '') {
      return false
    }
  }
  const curPriority: number = decodeID(curRole)
  if (required === 'editor') {
    return (curPriority & (1 << 8)) !== 0
  }
  if (required === 'admin') {
    return (curPriority & (1 << 24)) !== 0
  }
  return false
}

// 解码响应头
export function decodeRT (value: string, needDecode?: boolean): Header[] | null {
  let header
  if (needDecode !== undefined && needDecode) {
    header = Buffer.from(value, 'base64').toString()
  } else {
    header = value
  }
  if (header.length === 0) {
    return null
  }
  const h: Header[] = []
  header.split(' ').forEach((value) => {
    if (value !== '') {
      const r = value.split(':')
      h.push({ name: r[0], len: parseInt(r[1]) })
    }
  })
  return h
}

// 解码 question
export function decodeCT (header: string, value: string, key: number): Map<string, string> | undefined {
  const h = decodeRT(header, false)
  if (h === null || h.length === 0) {
    return
  }
  const buff = Buffer.from(value, 'base64')
  const l1 = key & 0xFF
  const l2 = (key >> 8) & 0xFF
  const l3 = (key >> 16) & 0xFF
  const l4 = (key >> 24) & 0xFF

  let N = 0
  let i = 0
  const tmp = new Map<string, string>()
  h.forEach(v => {
    N += v.len
    const ret = Buffer.alloc(v.len)
    let j = 0
    while (i <= N - 4) {
      ret[j++] = buff[i] ^ l1
      ret[j++] = buff[i + 1] ^ l2
      ret[j++] = buff[i + 2] ^ l3
      ret[j++] = buff[i + 3] ^ l4
      i += 4
    }
    while (i < N) {
      ret[j++] = buff[i] ^ l1
      i++
    }
    tmp.set(v.name, ret.toString('utf-8'))
  })
  return tmp
}

function trans (o1: number, o2: number): number {
  if (o1 <= 57) {
    o1 -= 48
  } else {
    o1 -= 87
  }

  o1 <<= 4

  if (o2 <= 57) {
    o2 -= 48
  } else {
    o2 -= 87
  }
  return o1 + o2
}

export function decodeID (value: string): number {
  const s = Buffer.from(value)
  if (s.length !== 25) {
    return 0
  }
  let m, c, n: number
  m = s[2]
  c = trans(s[3], s[4])
  n = (m ^ c)
  const l1 = n | 0XFFFFFF00

  m = s[11]
  c = trans(s[12], s[13])
  n = (m ^ c)
  n <<= 8
  const l2 = n | 0XFFFF00FF

  m = s[15]
  c = trans(s[16], s[17])
  n = (m ^ c)
  n <<= 16
  const l3 = n | 0XFF00FFFF

  m = s[22]
  c = trans(s[23], s[24])
  n = (m ^ c)
  n <<= 24
  const l4 = n | 0X00FFFFFF
  return l1 & l2 & l3 & l4
}

export function decodeValue (value: string, key: number): string {
  const buff = Buffer.from(value, 'base64')
  const l1 = key & 0xFF
  const l2 = (key >> 8) & 0xFF
  const l3 = (key >> 16) & 0xFF
  const l4 = (key >> 24) & 0xFF
  let i = 0
  let j = 0
  while (i <= buff.length - 4) {
    buff[j++] = buff[i] ^ l1
    buff[j++] = buff[i + 1] ^ l2
    buff[j++] = buff[i + 2] ^ l3
    buff[j++] = buff[i + 3] ^ l4
    i += 4
  }
  while (i < buff.length) {
    buff[j++] = buff[i] ^ l1
    i++
  }
  return buff.toString('utf8')
}

export function checkUser (): boolean {
  const u = blackUserTag
  const e1 = sessionStorage.getItem(u)
  if (e1 !== null && e1.length > 0) {
    return true
  }
  const e2 = localStorage.getItem(u)
  if (e2 !== null && e2.length > 0) {
    return true
  }
  let e3 = false
  const cookie = document.cookie
  if (cookie !== undefined && cookie !== null && cookie.length > 0) {
    const cs = cookie.split('; ')
    cs.forEach((c) => {
      if (c.indexOf(u) !== -1) {
        e3 = true
      }
    })
  }
  return e3
}

export function getRole (): string {
  let e1 = sessionStorage.getItem(role)
  if (e1 === null) {
    e1 = getFromLocal(role)
  }
  return e1
}

function getUserPriority (role: string):number {
  if (role !== '') {
    return decodeID(role)
  }
  return 0
}

export function isEditor (): boolean {
  const o = 1 << 8
  return getUserPriority(getRole()) >= o
}

export function subjectName2Code (name: string): string {
  if (name === '数据结构') {
    return 'CS'
  }

  if (name === '操作系统') {
    return 'OS'
  }

  if (name === '组成原理') {
    return 'CCP'
  }

  if (name === '计算机网络') {
    return 'NET'
  }

  if (name === '顺序刷题') {
    return 'SEQ'
  }
  return ''
}

export function subjectCode2Name (name: string): string {
  name = name.toUpperCase()
  if (name === 'CS') {
    return '数据结构'
  }

  if (name === 'OS') {
    return '操作系统'
  }

  if (name === 'CCP') {
    return '组成原理'
  }

  if (name === 'NET') {
    return '计算机网络'
  }

  if (name === 'SEQ') {
    return '顺序刷题'
  }

  if (name === 'FUN') {
    return '随机刷题'
  }

  return ''
}

export function getUserName (): string {
  let uname = sessionStorage.getItem(userName)
  if (uname === null) {
    uname = localStorage.getItem(userName)
    if (uname === null) {
      uname = 'K'
      uname = 'K'
    }
  }
  return uname
}

export function formatDate (date: Date): string {
  const y = date.getFullYear()
  const m = date.getMonth() + 1
  const d = date.getDate()
  const H = date.getHours()
  const M = date.getMinutes()
  const S = date.getSeconds()
  return `${y}/${m}/${d} ${H}:${M}:${S}`
}

export function getUserID (): number {
  const uid = sessionStorage.getItem(tokenName)
  if (uid === null) {
    const t = getFromLocal(tokenName)
    if (t === '') {
      return 0
    }
    return decodeID(t)
  }
  return decodeID(uid)
}
